﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Core
{
    public class AssemblySystem : Component, IAwake
    {
        private readonly Dictionary<Type, List<Type>> dict = new();
        private readonly IReadOnlyList<Type> emptyTypes = new List<Type>();

        private Type baseAttr;

        public void Awake()
        {
            log.d("AssemblySystem.Awake");
            dict.Clear();
            baseAttr = typeof(BaseAttribute);
        }

        public override void Dispose()
        {
            if (IsDisposed) return;
            base.Dispose();

            log.d("AssemblySystem.Dispose");
        }

        public void Parse(Assembly assembly)
        {
            foreach (Type type in assembly.GetTypes())
            {
                if (!type.IsDefined(baseAttr, false))
                {
                    continue;
                }

                object[] attributes = type.GetCustomAttributes(baseAttr, false);
                if (attributes.Length == 0)
                {
                    continue;
                }

                foreach (var element in attributes)
                {
                    if (element is BaseAttribute attr)
                    {
                        var attr_type = attr.GetType();
                        if (dict.ContainsKey(attr_type) == false)
                        {
                            dict.Add(attr_type, new List<Type>());
                        }

                        var list = dict[attr_type];
                        list.Add(type);
                    }
                }
            }
        }

        public IReadOnlyList<Type> GetAttrTypes(Type attr_type)
        {
            if (dict.TryGetValue(attr_type, out var types) == false)
            {
                return emptyTypes;
            }

            return types;
        }


        public bool IsAllowMulti(Type t)
        {
            var key = typeof(AllowMultipleAttribute);

            if (dict.TryGetValue(key, out var list) == false)
            {
                return false;
            }

            if (list == null || list.Count == 0)
            {
                return false;
            }

            return list.Contains(t);
        }
    }
}
